home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tricks of the Mac Game Programming Gurus
/
TricksOfTheMacGameProgrammingGurus.iso
/
More Source
/
C⁄C++
/
mgraph
/
mgraph.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-03-22
|
13KB
|
449 lines
/* Copyright 1994 Ralph Gonzalez */
/*
* FILE: mgraph.c
* AUTHOR: R. Gonzalez
* CREATED: March 19, 1990
* MODIFIED: March 15, 1994
* Adapted macgraph.c to agree with xgraph version
*
* PROJECT CONTENTS:
* yourfiles.c, mgraph.c, ANSI, MacTraps libraries, MacHeaders option.
*
* mgraph.c contains several Macintosh routines to supplement
* a typical stdio-type application with a graphics window, so that
* you don't have to deal directly with the Macintosh Toolbox (see
* below.) Your program must #include "mgraph.h" and must call
* init_graphics() first.
*
* The device coordinate system (usually given in pixels) is norm-
* alized to -1 to 1 horizontally by default. The vertical limits
* depend on the screen's aspect ratio. This is used for placing and
* sizing the graphics window.
*
* The window's own view coordinate system (which is used for
* drawing) is also normalized, by default to -1 to 1 horizontally
* and vertically.
*
* (The Macintosh Toolbox is a set of routines in ROM to produce the
* graphical user interface. These Toolbox functions are declared in
* MacHeaders. They are distinguished from my own functions by
* beginning with a capital letter.)
*/
# include "mgraph.h"
# include <stdio.h>
/*---------------------------------------------------------------------*/
/* The following #define's may be adjusted to your taste: */
/*---------------------------------------------------------------------*/
# define TITLE "\pGraphics"
/* # define MOVABLE */ /* use this if your program handles window moves */
# define BACKGROUND BLACK /* this is unused, see background_color(), below */
# define GRAPH_WIDTH 1. /* Window sizing & placement in */
# define GRAPH_HEIGHT 1. /* normalized screen coords (below). */
# define GRAPH_CENTER_X 0.
# define GRAPH_CENTER_Y 0.
/*---------------------------------------------------------------------*/
/* You can change these too if you want: */
/*---------------------------------------------------------------------*/
# define NORM_WIDTH 2. /* define normalized screen coords */
/* height depends on aspect ratio */
# define NORM_CENTER_X 0.
# define NORM_CENTER_Y 0.
# define VIEW_WIDTH 2. /* define normalized window coords for drawing */
# define VIEW_HEIGHT 2.
# define VIEW_CENTER_X 0.
# define VIEW_CENTER_Y 0.
/*---------------------------------------------------------------------*/
/* These represent the dimensions of the graphics window given in
* actual window coordinates. Also the window coords of its center:
*/
static double gGraphWidth,
gGraphHeight,
gGraphX,
gGraphY;
/* These represent the dimensions of normalized window coordinate
* system used for drawing, and coords of its center:
*/
static double gViewWidth,
gViewHeight,
gViewX,
gViewY;
static int transform_x(double),
transform_y(double);
/* globals for Macintosh implementation */
static WindowPtr gGraphWindow,
gConsoleWindow;
static CursHandle gCursor;
static color gPresentcolor;
# define NIL_POINTER 0L
# define MOVE_TO_FRONT -1L
# define REMOVE_ALL_EVENTS 0
# define VISIBLE 1
# define NO_GO_AWAY 0
# define NIL_REF_CON NIL_POINTER
/* These represent the dimensions of the physical display device in
* device coords, and the device coords of its center:
*/
static double gDeviceWidth,
gDeviceHeight,
gDeviceCenterX,
gDeviceCenterY;
/* These represent the dimensions of the normalized device coordinate
* system, used for window sizing. The desired coords for the center
* of the device are also given:
*/
static double gNormalDeviceWidth,
gNormalDeviceHeight,
gNormalDeviceCenterX,
gNormalDeviceCenterY;
/************************************************************************
* You must call init_graphics() at the beginning of main().
* Likely don't need all these initializations; they are taken from Mark
* & Reed's "Macintosh Programming Primer", Addison-Wesley, 1989
************************************************************************/
void init_graphics(void)
{
Rect rectangle;
double ratio,
temp;
int left,
top,
width,
height;
/* Need a stdio function call to produce the generic console environment
* BEFORE the remaining inits:
*/
printf("\n");
gConsoleWindow = FrontWindow();
InitGraf(&thePort);
InitFonts();
FlushEvents(everyEvent,REMOVE_ALL_EVENTS);
InitWindows();
InitMenus();
TEInit();
InitDialogs(NIL_POINTER);
InitCursor();
/* calculate device and normalized screen coord systems */
/* Note Macs use inverted y axis. This makes gDeviceHeight negative, */
/* which compensates the remaining equations automatically. */
gDeviceWidth = screenBits.bounds.right - screenBits.bounds.left;
gDeviceHeight = screenBits.bounds.top - screenBits.bounds.bottom;
gDeviceCenterX = gDeviceWidth/2;
gDeviceCenterY = -gDeviceHeight/2;
ratio = get_screen_aspect_ratio();
gNormalDeviceWidth = NORM_WIDTH;
gNormalDeviceHeight = gNormalDeviceWidth/ratio;
gNormalDeviceCenterX = NORM_CENTER_X;
gNormalDeviceCenterY = NORM_CENTER_Y;
/* convert window location from normalized to device coords */
temp = GRAPH_CENTER_X-GRAPH_WIDTH/2.;
ratio = gDeviceWidth/gNormalDeviceWidth;
left = gDeviceCenterX + (temp-gNormalDeviceCenterX) * ratio;
width = (ratio*GRAPH_WIDTH);
temp = GRAPH_CENTER_Y+GRAPH_HEIGHT/2.;
ratio = gDeviceHeight/gNormalDeviceHeight;
top = (int) (gDeviceCenterY + (temp-gNormalDeviceCenterY) * ratio);
height = (int) (-ratio*GRAPH_HEIGHT);
SetRect(&rectangle,left,top,left+width,top+height);
/* create graphics window */
# ifdef MOVABLE
gGraphWindow = NewWindow(NIL_POINTER,&rectangle,TITLE,
VISIBLE,noGrowDocProc,(WindowPtr) MOVE_TO_FRONT,NO_GO_AWAY,NIL_REF_CON);
# else
gGraphWindow = NewWindow(NIL_POINTER,&rectangle,TITLE,
VISIBLE,plainDBox,(WindowPtr) MOVE_TO_FRONT,NO_GO_AWAY,NIL_REF_CON);
# endif
SetPort(gGraphWindow);
gGraphX = width/2;
gGraphY = height/2;
gGraphWidth = width;
gGraphHeight = -height;
set_graphics_coords(VIEW_WIDTH,VIEW_HEIGHT,VIEW_CENTER_X,VIEW_CENTER_Y);
pen_color(WHITE);
background_color(BLACK);
erase_graphics();
}
/************************************************************************
* Return device aspect ratio: width/height
************************************************************************/
double get_screen_aspect_ratio(void)
{
double ratio;
ratio = gDeviceWidth/gDeviceHeight;
if (ratio < 0.)
ratio = -ratio;
return ratio;
}
/************************************************************************
* Define view coordinate system for draw_line(), draw_circle(), etc.
************************************************************************/
void set_graphics_coords(double width,double height,double x,double y)
{
gViewWidth = width;
gViewHeight = height;
gViewX = x;
gViewY = y;
}
/************************************************************************
* Transform view coordinate x to window coordinates
************************************************************************/
static int transform_x(double x)
{
return (int) (gGraphX+(x-gViewX)*gGraphWidth/gViewWidth);
}
/************************************************************************
* Transform view coordinate y to window coordinates
************************************************************************/
static int transform_y(double y)
{
return (int) (gGraphY+(y-gViewY)*gGraphHeight/gViewHeight);
}
/************************************************************************
* pen_color() sets the current drawing color.
************************************************************************/
void pen_color(color x)
{
gPresentcolor = x;
switch (x)
{
case 0: ForeColor(blackColor);
break;
case 1: ForeColor(whiteColor);
break;
case 2: ForeColor(redColor);
break;
case 3: ForeColor(yellowColor);
break;
case 4: ForeColor(greenColor);
break;
case 5: ForeColor(blueColor);
break;
case 6: ForeColor(cyanColor);
break;
case 7: ForeColor(magentaColor);
break;
default: break;
}
return;
}
/************************************************************************
* background_color() sets the background drawing color.
************************************************************************/
void background_color(color x)
{
switch (x)
{
case 0: BackColor(blackColor);
break;
case 1: BackColor(whiteColor);
break;
case 2: BackColor(redColor);
break;
case 3: BackColor(yellowColor);
break;
case 4: BackColor(greenColor);
break;
case 5: BackColor(blueColor);
break;
case 6: BackColor(cyanColor);
break;
case 7: BackColor(magentaColor);
break;
default: break;
}
return;
}
/************************************************************************
* erase_graphics() makes the graphics window the background color.
************************************************************************/
void erase_graphics(void)
{
EraseRect(&(gGraphWindow->portRect));
return;
}
/************************************************************************
* bring graphics window to front.
************************************************************************/
void graphics_to_front(void)
{
SelectWindow(gGraphWindow);
}
/************************************************************************
* draw_line() is used to draw lines using view coordinates.
************************************************************************/
void draw_line(double x1,double y1,double x2,double y2)
{
int window_x1,
window_y1,
window_x2,
window_y2;
window_x1 = transform_x(x1);
window_y1 = transform_y(y1);
window_x2 = transform_x(x2);
window_y2 = transform_y(y2);
MoveTo(window_x1,window_y1);
LineTo(window_x2,window_y2);
}
/************************************************************************
* Move present pen position to new position using view
* coordinates. Nothing is drawn.
************************************************************************/
void move_to(double x,double y)
{
int window_x,
window_y;
window_x = transform_x(x);
window_y = transform_y(y);
MoveTo(window_x,window_y);
return;
}
/************************************************************************
* Draw from present pen position to new position using view
* coordinates.
************************************************************************/
void draw_to(double x,double y)
{
int window_x,
window_y;
window_x = transform_x(x);
window_y = transform_y(y);
LineTo(window_x,window_y);
return;
}
/************************************************************************
* draw_circle() draws a circle using view coordinates.
************************************************************************/
void draw_circle(double center_x,double center_y,double r)
{
Rect myRect,
*myRectPtr;
int window_x,
window_y,
window_r;
window_x = transform_x(center_x);
window_y = transform_y(center_y);
window_r = (int) (r*(double) gGraphWidth/gViewWidth);
myRectPtr = &myRect;
myRectPtr->left = window_x-window_r;
myRectPtr->right = window_x+window_r;
myRectPtr->top = window_y-window_r;
myRectPtr->bottom = window_y+window_r;
FrameOval(&myRect);
return;
}
/************************************************************************
* fill_circle() draws a circle using view coordinates. The circle
* is filled with the present pen color
************************************************************************/
void fill_circle(double center_x,double center_y,double r)
{
Rect myRect,
*myRectPtr;
int window_x,
window_y,
window_r;
window_x = transform_x(center_x);
window_y = transform_y(center_y);
window_r = (int) (r*(double) gGraphWidth/gViewWidth);
myRectPtr = &myRect;
myRectPtr->left = window_x-window_r;
myRectPtr->right = window_x+window_r;
myRectPtr->top = window_y-window_r;
myRectPtr->bottom = window_y+window_r;
PaintOval(&myRect);
return;
}
/************************************************************************
* mouse_button_is_down() checks whether the mouse button is down,
* returns TRUE or FALSE.
************************************************************************/
boolean mouse_button_is_down(void)
{
return Button();
}
/************************************************************************
* get_mouse_location returns the mouse coordinates in terms of the
* view coordinate system. It uses the inverse transformation of that
* in transform_x() and transform_y().
************************************************************************/
void get_mouse_location(double *x_ptr,double *y_ptr)
{
Point mouseLoc;
int x,
y;
GetMouse(&mouseLoc);
x = mouseLoc.h;
y = mouseLoc.v;
*x_ptr = gViewX+(x-gGraphX)*gViewWidth/gGraphWidth;
*y_ptr = gViewY+(y-gGraphY)*gViewHeight/gGraphHeight;
return;
}
/************************************************************************
* wait until button is pressed
************************************************************************/
void wait(void)
{
while (!mouse_button_is_down())
;
}